//
//  Move.h
//  phi_four
//
//  Created by Snir Gazit on 3/9/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef Move_h
#define Move_h
#include "../HelpLibs/RandomGen.h"
#include "Lattice.h"
#include "../HelpLibs/QmcParameters.h"

typedef RandomVariable<MTGen, UniReal> UniRealVariable;
typedef RandomVariable<MTGen, UniInt> UniIntVariable;
typedef RandomVariable<MTGen, Binomial> BinomialVariable;
typedef RandomVariable<MTGen, Discrete> DiscreteVariable;
typedef UniRealVariable::param_type UniRealVariableParams;
typedef UniIntVariable::param_type UniIntVariableParams;
typedef BinomialVariable::param_type BinomialVariableParams;
typedef DiscreteVariable::param_type DiscreteVariableParams;
double calcProb(double lambda, double beta);
using namespace std;
class Move {
protected:
	MTGen *eng_;
	Lattice *lat_;
	UniRealVariable zeroOne_;
public:
	void init(MTGen * eng, Lattice *lat);
	void makeMove();
	bool accept(double p);
	bool checkMove();
};

// Worm Alg Moves

class ShiftMove: public Move {
	UniIntVariable chooseDirection_;
//	BinomialVariable createRemove_;
	BoltzWeightType CreateRatio_, RemoveRatio_;
	double g_;
public:
	void init(MTGen *eng, Lattice *lat, QmcParameters &qmcParameters,
			BoltzWeightType boltzRatio);
	void makeMove();
};

class JumpMove: public Move {
	UniIntVariable chooseSite_;
	BoltzWeightType boltzRatio_;
public:
	void init(MTGen *eng, Lattice *lat, QmcParameters &qmcParameters,
			BoltzWeightType boltzRatio);
	void makeMove();
};

// WormLoop Move
typedef boost::array<double, 2 * 2 * DIM> Weights;
double contProb(vector<double> Ns, double beta);
double clacProb(double lambda, double beta);

enum LoopMove {
	ACCEPT, CONT, ERASE
};

class CreateLoopMove: public Move {
	typedef vector<Site::BondData *> LoopData;
	typedef LoopData::iterator LoopDataIter;
	UniIntVariable chooseSite_;
	BoltzWeightType CreateRatio_, RemoveRatio_;
	Weights weights_;
	vector<double> NCont_;
	LoopData currentLoop_;
	int avWormLength_;
	double g_;
	double asym_;
#ifdef MULTILOOP
	int maxLoop_;
	double betaGibbs_;
#endif
	boost::accumulators::accumulator_set<double,
			boost::accumulators::stats<boost::accumulators::tag::mean> > eraseWorm_;
public:
	void init(MTGen *eng, Lattice *lat, QmcParameters &qmcParameters,
			BoltzWeightType boltzRatio);
	void setCoupeling(BoltzWeightType boltzRatio,double g);
	int makeMove();
	void nextStep();
	void eraseLoop();
	void getWeights();
	double getEraseProb();
	int chooseDirection();
	bool continueLoop();
	void setAvWormLength(int avWormLength);
};
#endif
